package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.constant.TableEnum;
import com.hbx.logs.annotation.MarkLog;
import com.hbx.logs.OperaTypeEnum;
import com.hbx.dto.BaseRequest;
import com.hbx.dto.resource.RecycleDto;
import com.hbx.exception.RspException;
import com.hbx.mapper.BlogMapper;
import com.hbx.mapper.PkMapper;
import com.hbx.mapper.ResourceMapper;
import com.hbx.model.Blog;
import com.hbx.model.Pk;
import com.hbx.model.Rank;
import com.hbx.model.RecycleBin;
import com.hbx.mapper.RecycleBinMapper;
import com.hbx.model.Resource;
import com.hbx.model.User;
import com.hbx.service.RankService;
import com.hbx.service.RecycleBinService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.service.UserService;
import com.hbx.utils.Result;
import com.hbx.utils.StringUtil;
import com.hbx.vo.PageBean;
import com.hbx.vo.PublicUserVo;
import com.hbx.vo.RankVo;
import com.hbx.vo.blog.BlogVo;
import com.hbx.vo.pk.PkIntemVo;
import com.hbx.vo.recycle.RecycleDetailVo;
import com.hbx.vo.recycle.RecycleVo;
import com.hbx.vo.res.ResourceVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hbx
 * @since 2022-01-27
 */
@Service
public class RecycleBinServiceImpl extends ServiceImpl<RecycleBinMapper, RecycleBin> implements RecycleBinService {

    public static final Integer BLOG_CODE = 1;
    public static final Integer RES_CODE = 2;
    public static final Integer PK_CODE = 3;

    @Autowired
    private RecycleBinMapper recycleBinMapper;

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RankService rankService;

    @Autowired
    private PkMapper pkMapper;

    /**
     * 删除文件
     *
     * @param dto
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.DELETE, tables = {TableEnum.PLATFORM_RESOURCE, TableEnum.RECYCLE_BIN}, desc = "管理员删除文件,移到回收站")
    public void addRecycle(RecycleDto dto, Result r) {
        User user = AuthCacheService.getUser();
        Integer fileType = dto.getFileType();
        if (fileType == null) {
            r.setCode(400).setMsg("入参错误");
            return;
        }
        QueryWrapper<RecycleBin> wrapper = new QueryWrapper<>();
        wrapper.eq("main_id",dto.getMainId());
        wrapper.eq("file_type",dto.getFileType());
        List<RecycleBin> recycleBins = recycleBinMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(recycleBins)){
            throw new RspException("删除失败");
        }

        RecycleBin report = new RecycleBin();
        BeanUtils.copyProperties(dto, report);
        report.setOperaAdmin(user.getUserId());
        report.setRemoveDate(new Date());
        int insert = recycleBinMapper.insert(report);
        if (insert != 1) {
            throw new RspException("删除失败");
        }

        if (fileType.equals(BLOG_CODE)) {
            // 博客
            Blog blog = new Blog();
            blog.setBlogId(dto.getMainId());
            blog.setBlogIsDeleted(1);
            int result = blogMapper.updateById(blog);
            if (result == 1) {
                r.setCode(200).setMsg("博客删除成功");
                return;
            }
            throw new RspException("博客删除失败");
        } else if (fileType.equals(RES_CODE)) {
            // 资源
            Resource resource = new Resource();
            resource.setResId(dto.getMainId());
            resource.setResIsDeleted(1);
            int result = resourceMapper.updateById(resource);
            if (result == 1) {
                r.setCode(200).setMsg("资源删除成功");
                return;
            }
            throw new RspException("资源删除失败");
        } else if (fileType.equals(PK_CODE)) {
            // 竞技pk
            // 资源
            Pk pk = new Pk();
            pk.setId(dto.getMainId());
            pk.setPkDelete(1);
            int result = pkMapper.updateById(pk);
            if (result == 1) {
                r.setCode(200).setMsg("删除成功");
                return;
            }
            throw new RspException("删除失败");
        } else {
            r.setCode(201).setMsg("暂未开通fileType为其他");
        }
    }

    /**
     * 获得回收站列表
     * @param r
     */
    @Override
    public void recycleList(BaseRequest request, Result r) {
        Page<RecycleBin> page = new Page<>(request.getPageNum(), request.getPageSize());
        PageBean pageBean = new PageBean();
        QueryWrapper<RecycleBin> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("remove_date");
        IPage<RecycleBin> binIPage = recycleBinMapper.selectPage(page, wrapper);
        pageBean.setTotal(binIPage.getTotal());
        pageBean.setPageNum(binIPage.getCurrent());
        pageBean.setPageSize(binIPage.getSize());
        List<RecycleBin> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records)){
            List<RecycleVo> list = new ArrayList<>();
            records.stream().forEach(recode -> {
                RecycleVo vo = new RecycleVo();
                BeanUtils.copyProperties(recode, vo);
                // 查询管理员用户
                User admin = userService.getById(recode.getOperaAdmin());
                if (!ObjectUtils.isEmpty(admin)){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(admin.getUserId());
                    userVo.setAvatar(admin.getAvator());
                    userVo.setUserName(admin.getLoginName());
                    List<Rank> rankList = rankService.getRankList(admin.getUserId());
                    if (!CollectionUtils.isEmpty(rankList)){
                        List<RankVo> voList = new ArrayList<>();
                        rankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            voList.add(rankVo);
                        });
                        userVo.setRankList(voList);
                    }
                    vo.setAdmin(userVo);
                }
                list.add(vo);
            });
            pageBean.setData(list);
        }
        r.setCode(200).setData(pageBean);
    }

    /**
     * 永久删除文件
     * @param id
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.DELETE, tables = {TableEnum.RECYCLE_BIN}, desc = "管理员永久删除回收站文件")
    public void recycleRemove(Integer id, Result r) {
        RecycleBin recycleBin = recycleBinMapper.selectById(id);
        if (recycleBin == null){
            r.setCode(201).setMsg("文件不存在");
            return;
        }
        Integer mainId = recycleBin.getMainId();
        Integer fileType = recycleBin.getFileType();
        Integer result = 0;
        if (fileType == BLOG_CODE){
            // 博客
            result = blogMapper.deleteById(mainId);
        }else if(fileType == RES_CODE){
            // 资源
            result = resourceMapper.deleteById(mainId);
        }else if(fileType == PK_CODE){
            //pk
            result = pkMapper.deleteById(mainId);
        }
        if (result != 1){
            throw new RspException("文件删除失败");
        }
        int i = recycleBinMapper.deleteById(id);
        if (i != 1){
            throw new RspException("文件删除失败");
        }
        r.setCode(200).setMsg("文件删除成功");
    }

    /**
     * 文件恢复
     * @param id
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.DELETE, tables = {TableEnum.RECYCLE_BIN}, desc = "管理员恢复资源")
    public void recycleRecovery(Integer id, Result r) {
        RecycleBin recycleBin = recycleBinMapper.selectById(id);
        if (recycleBin == null){
            r.setCode(201).setMsg("文件不存在");
            return;
        }
        Integer mainId = recycleBin.getMainId();
        Integer fileType = recycleBin.getFileType();
        Integer result = 0;
        if (fileType == BLOG_CODE){
            // 博客
            Blog blog = new Blog();
            blog.setBlogId(mainId);
            blog.setBlogIsDeleted(0);
            result = blogMapper.updateById(blog);
        }else if(fileType == RES_CODE){
            // 资源
            Resource resource = new Resource();
            resource.setResId(mainId);
            resource.setResIsDeleted(0);
            result = resourceMapper.updateById(resource);
        }else if(fileType == PK_CODE){
            //pk
            Pk pk = new Pk();
            pk.setId(mainId);
            pk.setPkDelete(0);
            result = pkMapper.updateById(pk);
        }
        if (result != 1){
            throw new RspException("文件恢复失败");
        }
        int i = recycleBinMapper.deleteById(id);
        if (i != 1){
            throw new RspException("文件恢复失败");
        }
        r.setCode(200).setMsg("文件恢复成功");
    }

    /**
     * 清空回收站
     * @param r
     */
    @Override
    @Transactional
    @MarkLog(operate = OperaTypeEnum.DELETE, tables = {TableEnum.RECYCLE_BIN}, desc = "管理员清空回收站")
    public void recycleClear(Result r) {
        List<RecycleBin> list = recycleBinMapper.selectList(null);
        if (CollectionUtils.isEmpty(list)){
            r.setCode(200).setMsg("回收站为空");
            return;
        }
        Map<Integer, List<RecycleBin>> typeMap = list.stream().collect(Collectors.groupingBy(RecycleBin::getFileType));
        List<RecycleBin> resList = typeMap.get(BLOG_CODE);
        List<RecycleBin> blogList = typeMap.get(RES_CODE);
        List<RecycleBin> pkList = typeMap.get(PK_CODE);
        List<Integer> resIds = new ArrayList<>();
        List<Integer> blogIds = new ArrayList<>();
        List<Integer> pkIds  = new ArrayList<>();
        if(!CollectionUtils.isEmpty(resList)){
            resIds = resList.stream().map(RecycleBin::getMainId).collect(Collectors.toList());
        }
        if(!CollectionUtils.isEmpty(blogList)){
            blogIds = blogList.stream().map(RecycleBin::getMainId).collect(Collectors.toList());
        }
        if(!CollectionUtils.isEmpty(pkList)){
            pkIds = pkList.stream().map(RecycleBin::getMainId).collect(Collectors.toList());
        }

        if (!CollectionUtils.isEmpty(resIds)){
            resourceMapper.deleteBatchIds(resIds);
        }

        if (!CollectionUtils.isEmpty(blogIds)){
            blogMapper.deleteBatchIds(blogIds);
        }

        if (!CollectionUtils.isEmpty(pkIds)){
            pkMapper.deleteBatchIds(pkIds);
        }

        int delete = recycleBinMapper.delete(null);
        if (delete > 0){
            r.setCode(200).setMsg("操作成功");
            return;
        }
        throw new RspException("操作失败");
    }

    /**
     * 获取回收站详情
     * @param id
     * @param r
     */
    @Override
    public void getRecycleInfo(Integer id, Result r) {
        // 获取数据
        RecycleBin recycleBin = recycleBinMapper.selectById(id);
        if (recycleBin == null){
            r.setCode(201).setMsg("文件不存在");
            return;
        }
        RecycleDetailVo vo = new RecycleDetailVo();
        BeanUtils.copyProperties(recycleBin, vo);
        Integer operaAdmin = recycleBin.getOperaAdmin();
        if (operaAdmin == null){
            r.setCode(201).setMsg("文件异常,请联系管理员");
            return;
        }
        User admin = userService.getById(operaAdmin);
        if (ObjectUtils.isEmpty(admin)){
            r.setCode(201).setMsg("文件异常,请联系管理员");
            return;
        }
        PublicUserVo userVo = new PublicUserVo();
        userVo.setUserId(admin.getUserId());
        userVo.setUserName(admin.getLoginName());
        userVo.setAvatar(admin.getAvator());
        userVo.setType(admin.getType());
        List<Rank> rankList = rankService.getRankList(admin.getUserId());
        if (!CollectionUtils.isEmpty(rankList)){
            List<RankVo> voList = new ArrayList<>();
            rankList.stream().forEach(rank -> {
                RankVo rankVo = new RankVo();
                BeanUtils.copyProperties(rank, rankVo);
                voList.add(rankVo);
            });
            userVo.setRankList(voList);
        }
        vo.setAdmin(userVo);
        Integer type = recycleBin.getFileType();
        Integer mainId = recycleBin.getMainId();
        if (type == null || mainId == null){
            r.setCode(201).setMsg("文件异常,请联系管理员");
            return;
        }
        if (BLOG_CODE.equals(type)){
            BlogVo blogVo = new BlogVo();
            Blog blog = blogMapper.selectById(mainId);
            if (blog != null){
                BeanUtils.copyProperties(blog, blogVo);
                if (StringUtils.hasLength(blog.getBlogLable())){
                    blogVo.setBlogTags(StringUtil.stringSpiltList(blog.getBlogLable(), ","));
                }
                User user = userService.getById(blog.getBlogUserid());
                if (user != null){
                    BlogVo.UserVo blogUser = new BlogVo.UserVo();
                    blogUser.setUserName(user.getLoginName());
                    blogUser.setAvatar(user.getAvator());
                    blogUser.setUserId(user.getUserId());
                    List<Rank> blogUserRankList = rankService.getRankList(user.getUserId());
                    if (!CollectionUtils.isEmpty(blogUserRankList)){
                        List<RankVo> voList = new ArrayList<>();
                        blogUserRankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            voList.add(rankVo);
                        });
                        blogUser.setRankList(voList);
                    }
                    blogVo.setUser(blogUser);
                }
            }
            vo.setBlogVo(blogVo);
        } else if (RES_CODE.equals(type)){
            ResourceVo resVo = new ResourceVo();
            Resource res = resourceMapper.selectById(mainId);
            if (res != null){
                BeanUtils.copyProperties(res, resVo);
                if (StringUtils.hasLength(res.getResTags())){
                    resVo.setResTags(StringUtil.stringSpiltList(res.getResTags(), ","));
                }
                // 设置user
                User user = userService.getById(res.getResUserid());
                if (user != null){
                    ResourceVo.UserVo resUser = new ResourceVo.UserVo();
                    resUser.setUserName(user.getLoginName());
                    resUser.setAvatar(user.getAvator());
                    resUser.setUserId(user.getUserId());
                    List<Rank> resUserRankList = rankService.getRankList(user.getUserId());
                    if (!CollectionUtils.isEmpty(resUserRankList)){
                        List<RankVo> voList = new ArrayList<>();
                        resUserRankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            voList.add(rankVo);
                        });
                        resUser.setRankList(voList);
                    }
                    resVo.setUser(resUser);
                }
            }
            vo.setResVo(resVo);
        } else if (PK_CODE.equals(type)){
            PkIntemVo pkVo = new PkIntemVo();
            Pk pk = pkMapper.selectById(mainId);
            if (pk != null){
                BeanUtils.copyProperties(pk, pkVo);
                PublicUserVo pkUser = new PublicUserVo();
                User pkPubUser = userService.getById(pk.getPkPublicUserId());
                if (pkPubUser != null){
                    pkUser.setUserId(pkPubUser.getUserId());
                    pkUser.setUserName(pkPubUser.getLoginName());
                    pkUser.setAvatar(pkPubUser.getAvator());
                    List<Rank> pkUserRankList = rankService.getRankList(pkPubUser.getUserId());
                    if (!CollectionUtils.isEmpty(pkUserRankList)){
                        List<RankVo> voList = new ArrayList<>();
                        pkUserRankList.stream().forEach(rank -> {
                            RankVo rankVo = new RankVo();
                            BeanUtils.copyProperties(rank, rankVo);
                            voList.add(rankVo);
                        });
                        pkUser.setRankList(voList);
                    }
                    pkVo.setUser(pkUser);
                }
            }
            vo.setPkVo(pkVo);
        } else {
            r.setCode(201).setMsg("文件类型异常,请联系管理员");
            return;
        }
        r.setCode(200).setData(vo).setMsg("请求处理完成");
    }
}
